package com.bree.erp.jsf.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

import org.apache.log4j.Logger;

import com.bree.erp.entity.MovementType;
import com.bree.erp.entity.PartUnit;
import com.bree.erp.entity.Project;
import com.bree.erp.entity.Returns;
import com.bree.erp.entity.ReturnsBalance;
import com.bree.erp.entity.Warehouse;
import com.bree.erp.entity.WarehousePartUnitId;
import com.bree.erp.jsf.httpsess.Clipboard;
import com.bree.erp.jsf.httpsess.UserSessionData;
import com.bree.erp.service.ProjectService;
import com.bree.erp.service.PurchaseOrderService;

@ManagedBean(name = "dtReturnWithdrawalView")
@ViewScoped
public class ReturnWithdrawalView  implements Serializable{

	private static final long serialVersionUID = 1L;

	private static Logger LOG = Logger.getLogger(ReturnWithdrawalView.class);

	@ManagedProperty(value="#{userSession}")
	private UserSessionData userSession;
	
	@ManagedProperty(value="#{clipboardSession}")
	private Clipboard clipboard;

	@EJB
	private ProjectService projectService;
	
	@EJB
	private PurchaseOrderService poService;
	
	private List<Returns> reserveList;
	private Map<WarehousePartUnitId, Double> quantityMap;
	
	private Long projectId;
	private String description;
	
	@PostConstruct
	public void init() {
		reserveList = new ArrayList<Returns>();
		
		if(clipboard.isNotEmpty()) {
			reserveList.addAll(clipboard.getReserveList());
		}
		
		recount();
	}
	
	private void recount() {
		
		if(quantityMap == null) {
			quantityMap = new HashMap<WarehousePartUnitId, Double>();
		}

		int count = 0;
		for(Returns returns : reserveList) {
			returns.setItemNumber(++count);
			returns.setId(count * -1L);
			
			WarehousePartUnitId whpuid = new WarehousePartUnitId(returns.getWarehouse(), returns.getPartUnit());
			quantityMap.put(whpuid, returns.getQuantity());
		}
	}
	
	public void remove(Long id) {
		
		Returns template = new Returns();
		template.setId(id);
		
		int idx = reserveList.indexOf(template);
		if(idx >= 0) {
			Returns byebye = reserveList.get(idx);
			quantityMap.put(byebye.getWarehousePartUnitId(), null);

			reserveList.remove(byebye);
		}
		
		recount();
		
	}
	
	public String withdraw() {
		
		LOG.debug("Requesting for withdrawal...");
		
		Map<Warehouse, List<Returns>> map = new HashMap<Warehouse, List<Returns>>();
		
		for(Returns returns : reserveList) {
			
			Warehouse wh = returns.getWarehouse();
			List<Returns> list = map.get(wh);
			if(list == null) {
				list = new ArrayList<Returns>();
				map.put(wh, list);
			}
			
			list.add(returns);
		}
		
		for(Warehouse warehouse : map.keySet()) {
			
			poService.withdraw(warehouse, projectId, description, map.get(warehouse), userSession.getLoggedInUser());
			
		}
		
		return "/inv/pickups";
	}

	public void reserve(ReturnsBalance selectedItem, double quantity) {
		
		Warehouse warehouse = selectedItem.getWarehouse();
		PartUnit partUnit = selectedItem.getPartUnit();
		
		Returns returns = findCache(warehouse, partUnit);
		if(returns == null) {
			returns = new Returns();
			returns.setPartUnit(partUnit);
			returns.setWarehouse(warehouse);
			returns.setQuantity(quantity);
			returns.setMovementType(MovementType.RESERVE);
			
			int count = reserveList.size() + 1;
			returns.setItemNumber(count);
			returns.setId(count * -1L);
			
			reserveList.add(returns);
		} else {
			// update existing
			double updateQty = returns.getQuantity() + quantity;
			returns.setQuantity(updateQty);
		}
		
		WarehousePartUnitId whpuid = new WarehousePartUnitId(returns.getWarehouse(), returns.getPartUnit());
		quantityMap.put(whpuid, returns.getQuantity());
		
	}

	private Returns findCache(Warehouse warehouse, PartUnit partUnit) {
		
		for(Returns item : reserveList) {
			if(warehouse.equals(item.getWarehouse()) && partUnit.equals(item.getPartUnit())) {
				return item;
			}
		}
		
		return null;
	}

	public List<Project> getProjects() {
		
		List<Project> list = new ArrayList<Project>();
		list.addAll(projectService.list());
		
		return list;
		
	}
	
	public boolean isRequestDisabled() {
		
		return reserveList.isEmpty();
	}

	/**
	 * @return the userSession
	 */
	public UserSessionData getUserSession() {
		return userSession;
	}

	/**
	 * @param userSession the userSession to set
	 */
	public void setUserSession(UserSessionData userSession) {
		this.userSession = userSession;
	}

	/**
	 * @return the clipboard
	 */
	public Clipboard getClipboard() {
		return clipboard;
	}

	/**
	 * @param clipboard the clipboard to set
	 */
	public void setClipboard(Clipboard clipboard) {
		this.clipboard = clipboard;
	}

	/**
	 * @return the reserveList
	 */
	public List<Returns> getReserveList() {
		return reserveList;
	}

	/**
	 * @return the projectId
	 */
	public Long getProjectId() {
		return projectId;
	}

	/**
	 * @param projectId the projectId to set
	 */
	public void setProjectId(Long projectId) {
		this.projectId = projectId;
	}

	/**
	 * @return the description
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * @param description the description to set
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * @return the quantityMap
	 */
	public Map<WarehousePartUnitId, Double> getQuantityMap() {
		return quantityMap;
	}
	
}
